'''
A pulish/subscribe tracker for Ping-pong servers and clients.

@author: oraby
'''

import random

from twisted.internet import reactor
from twisted.internet.protocol import ServerFactory
from twisted.protocols.basic import LineOnlyReceiver



class DataSingleton():
    connectedNotes = []
    def __init__(self):
        self.connectedNotes = []
        
    def getNode(self):
        if DataSingleton.connectedNotes:
            x = random.randrange(len(DataSingleton.connectedNotes))
            node = DataSingleton.connectedNotes[x]
        else:
            node = None
        return node
DataSingleton = DataSingleton()


class connectionHandler(LineOnlyReceiver):    
    def lineReceived(self, line):
        self._parseLine(line)
        pass
    
    def _parseLine(self,line):
        op, params = line.split(":",1)
        
        #switch
        op = op.strip().upper()
        if op == "GET":
            self._getNode()
        elif op == "PUT":
            self._putNode(params)
        else:
            line = "-1:Wrong operation Requested, Terminating connection" 
            self.sendLine(line)
            self.transport.loseConnection()
        
    def _putNode(self,params):
        #The only param I'm expecting is the port
        params = params.strip().split()
        if len(params) < 1:
            line = "putReply:-2 Wrong operation Requested, Terminating connection"
        else:
            params = params[0]
            try:
                port = int(params)
            except ValueError:
                line = "putReply:-3 Invalid Parameter Value"
            else:
                peerAddr = self.transport.getPeer()
                #IP = peerAddr.host
                peerAddr.port = port
                DataSingleton.connectedNotes.append(peerAddr)
                node = DataSingleton.getNode()
                line = "putReply:" + node.host + " " + str(node.port)
        self.sendLine(line)
        self.transport.loseConnection()
        
        #print "Sent:", node.host + ":" + str(node.port) , "to " + \
        #        peerAddr.host + ":" + str(peerAddr.port)
        

class Tracker(ServerFactory):
    protocol = connectionHandler
    
    def __init__(self):
        self._nodesServed = 0
        
    def buildProtocol(self, addr):
        self._nodesServed +=1
        return ServerFactory.buildProtocol(self, addr)

def main():
    reactor.listenTCP(2000,Tracker())
    reactor.run()
    
if __name__ == '__main__':
    main()